import { _decorator, Component, log, Node, assetManager } from 'cc'

export class ResMgr extends Component {
  public static Instance: ResMgr = null as unknown as ResMgr

  private abs: any = {}
  private total: number = 0
  private now: number = 0
  private progressFunc: Function | null = null
  private endFunc: Function | null = null

  private nowAb: number = 0
  private totalAb: number = 0

  start() {}

  update(deltaTime: number) {}

  onLoad() {
    if (ResMgr.Instance === null) {
      log('[ResMgr] Instance')
      ResMgr.Instance = this
    } else {
      log('[ResMgr] Instance Destroy')
      this.destroy()
      return
    }
  }

  private loadAssetsBundle(abName: string, endFunc: Function): void {
    assetManager.loadBundle(abName, (err, bundle) => {
      if (err != null) {
        console.log('[ResMgr] Load AssetsBundle Error: ' + abName)
        this.abs[abName] = null
      } else {
        console.log('[ResMgr] Load AssetsBundle Success: ' + abName)
        this.abs[abName] = bundle
      }
      if (endFunc) endFunc()
    })
  }

  private loadRes(abBundle: any, url: any, typeClass: any): void {
    abBundle.load(url, typeClass, (err: any, asset: any) => {
      this.now++
      if (err) console.log('[error] load res ' + url + ' error: ' + err)
      else console.log('[success] load res ' + url + ' success !')
      if (this.progressFunc) this.progressFunc(this.now, this.total)
      if (this.now >= this.total) if (this.endFunc) this.endFunc()
    })
  }

  private loadAssetsInAssetsBundle(resPkg: any): void {
    for (let k in resPkg) {
      let urlSet = resPkg[k].urls
      let typeClass = resPkg[k].assetType
      for (let i = 0; i < urlSet.length; i++) {
        this.loadRes(this.abs[k], urlSet[i], typeClass)
      }
    }
  }

  public preloadResPackage(
    resPkg: any,
    progressFunc: Function,
    endFunc: Function
  ): void {
    this.total = 0
    this.now = 0
    this.totalAb = 0
    this.nowAb = 0
    this.progressFunc = progressFunc
    this.endFunc = endFunc
    for (let k in resPkg) {
      this.totalAb++
      this.total += resPkg[k].urls.length
    }
    for (let k in resPkg) {
      this.loadAssetsBundle(k, () => {
        this.nowAb++
        if (this.nowAb === this.totalAb) {
          this.loadAssetsInAssetsBundle(resPkg)
        }
      })
    }
  }

  public unloadResPkg(resPkg: any): void {}

  public getAsset(abName: string, url: string): any {
    let bundle = assetManager.getBundle(abName)
    if (bundle === null) {
      console.log('[error]: ' + abName + ' AssetsBundle not loaded !')
      return null
    }
    return bundle.get(url)
  }

  public releaseResPackage(resPkg: any) {
    for (let k in resPkg) {
      let urlSet = resPkg[k].urls
      for (let i = 0; i < urlSet.length; i++) {
        let bundle: any = assetManager.getBundle(k)
        if (bundle === null) {
          console.log('[error]: ' + k + ' AssetsBundle not loaded !')
          continue
        }
        assetManager.releaseAsset(bundle.get(urlSet[i]))
      }
    }
  }
}
